package com.compomics.prioritizer.general.gui;

import com.compomics.prioritizer.db.accessors.*;
import com.compomics.prioritizer.general.PrioritizerSingelton;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
import java.sql.SQLException;
import java.sql.Connection;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.*;

/**
 * Created by IntelliJ IDEA.
 * User: Niklaas Colaert
 * Date: 31-okt-2008
 * Time: 9:31:36
 * To change this template use File | Settings | File Templates.
 */
public class PriorityListGUI extends JFrame {
    private JPanel projectInfoPanel;
    private JPanel projectListPanel;
    private JComboBox cmbInstrument;
    private JList projectList;
    private JButton downButton;
    private JButton upButton;
    private JPanel jpanContent;
    private JButton saveChangesButton;
    private JButton changeSelectedProjectToButton;
    private JComboBox cmbNewInstrument;


    //the connection
    public Connection iConnPriority;
    //the instruments
    public Instrument[] iInstruments;
    //the projects
    public Project[] iProjects;
    //the selected instrument
    public Instrument iInstrument;
    //the selected project
    public Project iProject;
    //boolean: true if the the priorities are changed for this instrument
    public boolean iChangesDone = false;
    /*
     * The user role
     * 1 =  normal user
     * 2 =  user that may change priorities
     * 3 =  operator
     */
    public int iRole = -1;
    private User iUser;
    private boolean iProjectModificationsChanged;
    private ProjectPanelGui iProjectPanel;
    private PrioritizerSingelton iPrioritizerSingelton;

    public PriorityListGUI(Connection aConnPriority, User aUser) {
        super("Project priority list");
        this.iConnPriority = aConnPriority;
        this.iUser = aUser;
        iPrioritizerSingelton = PrioritizerSingelton.getInstance();


        $$$setupUI$$$();
        this.iRole = iUser.getRole();

        saveChangesButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                storePriorityChanges();
            }
        });
        cmbInstrument.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    stateChangedInstrument((Instrument) e.getItem());
                }
            }
        });
        projectList.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                iProject = (Project) projectList.getSelectedValue();
                iProjectPanel.loadProject(iProject);
            }
        });


        upButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                moveProjectUp();
            }
        });
        downButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                moveProjectDown();
            }
        });
        changeSelectedProjectToButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                iProject = (Project) projectList.getSelectedValue();
                changeInstrument(iProject);
            }
        });


        if (iRole != 2) {
            upButton.setVisible(false);
            downButton.setVisible(false);
            saveChangesButton.setVisible(false);
            cmbNewInstrument.setVisible(false);
            changeSelectedProjectToButton.setVisible(false);
        }

        stateChangedInstrument((Instrument) cmbInstrument.getSelectedItem());
        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        this.setLocation((screen.width / 5), (screen.height / 10));
        setContentPane(jpanContent);
        this.setSize(1024, 800);
        this.setVisible(true);


    }


    public void storePriorityChanges() {
        iProjectPanel.showProgressBar();
        for (int p = 0; p < iProjects.length; p++) {
            Project lProject = iProjects[p];
            long oldPriority = lProject.getPriority();
            if (p + 1 != lProject.getPriority()) {
                lProject.setPriority(p + 1);
                try {
                    lProject.updatePriorityProject(iConnPriority);
                    if (oldPriority != 1 && lProject.getPriority() == 1) {
                        MailSendingPanel lMail = new MailSendingPanel();
                        iPrioritizerSingelton.addMailSendingPanel(lMail);
                        lMail.projectTopPriority(iConnPriority, lProject);
                    }
                } catch (SQLException e) {
                    JOptionPane.showMessageDialog(this, new String[]{"Unable to store changed priority:  ", e.getMessage()}, "Error!", JOptionPane.ERROR_MESSAGE);
                }
            }

        }
        // an e-mail is sent if the admin changes the priorities, not if the mass spec operator changes it
        if (iRole == 2) {
            MailSendingPanel lMail = new MailSendingPanel();
            iPrioritizerSingelton.addMailSendingPanel(lMail);
            lMail.prioritiesChanged(iConnPriority, iInstrument.getInstrumentid());
        }
        iChangesDone = false;
        iProjectPanel.stopProgressBar();
    }

    public void changeInstrument(Project aProject) {
        //get the new instrument
        Instrument lNewInstrument = (Instrument) cmbNewInstrument.getSelectedItem();
        //get the old instrument
        Instrument lOldInstrument = (Instrument) cmbInstrument.getSelectedItem();
        try {
            Project[] lProjectsOfNew = Project.getAllUnfinishedProjectsForInstrument(iConnPriority, lNewInstrument.getInstrumentid());
            Project[] lProjectsOfOld = Project.getAllUnfinishedProjectsForInstrument(iConnPriority, lOldInstrument.getInstrumentid());

            // get the priority for the project that will be changed
            int lPriorityNew = (int) (lProjectsOfNew[lProjectsOfNew.length - 1].getPriority() + 1);

            aProject.setL_instrumentid_accepted(lNewInstrument.getInstrumentid());
            aProject.setPriority(lPriorityNew);
            aProject.update(iConnPriority);

            // change all the project priorities of the old instrument
            boolean lOldProjectFound = false;
            for (int i = 0; i < lProjectsOfOld.length; i++) {
                if (lOldProjectFound) {
                    lProjectsOfOld[i].setPriority(lProjectsOfOld[i].getPriority() - 1);
                    lProjectsOfOld[i].update(iConnPriority);
                } else if (lProjectsOfOld[i].getProjectid() == aProject.getProjectid()) {
                    lOldProjectFound = true;
                }
            }

            MailSendingPanel lMail = new MailSendingPanel();
            iPrioritizerSingelton.addMailSendingPanel(lMail);
            lMail.instrumentChanged(iConnPriority, aProject);
            iProjects = Project.getAllUnfinishedProjectsForInstrument(iConnPriority, lOldInstrument.getInstrumentid());
            projectList.setListData(iProjects);
            JOptionPane.showMessageDialog(this, "Saved project updates succesfully!", "Project updates saved!", JOptionPane.INFORMATION_MESSAGE);
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(this, new String[]{"Unable to store changed instrument:  ", e.getMessage()}, "Error!", JOptionPane.ERROR_MESSAGE);
        }
    }

    public void moveProjectUp() {
        int selectedInt = projectList.getSelectedIndex();
        if (selectedInt > 0) {
            iChangesDone = true;
            Project lProject = iProjects[selectedInt - 1];
            iProjects[selectedInt - 1] = iProjects[selectedInt];
            iProjects[selectedInt] = lProject;
        }
        projectList.setListData(iProjects);
    }

    public void moveProjectDown() {
        int selectedInt = projectList.getSelectedIndex();
        if (selectedInt != iProjects.length - 1 && selectedInt >= 0) {
            iChangesDone = true;
            Project lProject = iProjects[selectedInt + 1];
            iProjects[selectedInt + 1] = iProjects[selectedInt];
            iProjects[selectedInt] = lProject;
        }
        projectList.setListData(iProjects);
    }


    public void gatherData() {
        this.findInstruments();
    }


    public void stateChangedInstrument(Instrument aInstrument) {
        try {
            if (iChangesDone) {

                if (JOptionPane.showConfirmDialog(null, "You changed the project priorities for " + iInstrument.getName() + ", \n do you want to save the changes now. If not, they will be lost!", "Save changes first?", JOptionPane.OK_CANCEL_OPTION) == 0) {
                    storePriorityChanges();
                } else {
                    iChangesDone = false;
                }
            }
            iInstrument = aInstrument;

            if (iInstrument.getName().equalsIgnoreCase("Old projects")) {
                iProjects = Project.getAllFinishedProjects(iConnPriority, aInstrument.getInstrumentid());
                projectList.setListData(iProjects);
                if (iProjects[0] != null) {
                    iProjectPanel.loadProject(iProjects[0]);
                }

                upButton.setVisible(false);
                downButton.setVisible(false);
                saveChangesButton.setVisible(false);
                cmbNewInstrument.setVisible(false);
                changeSelectedProjectToButton.setVisible(false);

            } else {
                iProjects = Project.getAllUnfinishedProjectsForInstrument(iConnPriority, aInstrument.getInstrumentid());
                projectList.setListData(iProjects);
                if (iProjects[0] != null) {
                    iProjectPanel.loadProject(iProjects[0]);
                }
                if (iRole == 2) {
                    upButton.setVisible(true);
                    downButton.setVisible(true);
                    saveChangesButton.setVisible(true);
                    cmbNewInstrument.setVisible(true);
                    changeSelectedProjectToButton.setVisible(true);
                }
            }
        } catch (SQLException sqle) {
            JOptionPane.showMessageDialog(this, new String[]{"Unable to find projects for this instrument:  ", sqle.getMessage()}, "Error!", JOptionPane.ERROR_MESSAGE);
        } catch (ArrayIndexOutOfBoundsException e) {
            //now projects found for this instrument
        }
    }


    /**
     * This method collects all instruments.
     * It fills the 'iInstruments' cache.
     */
    private void findInstruments() {
        try {
            iInstruments = Instrument.getAllInstruments(iConnPriority);
        } catch (SQLException sqle) {
            JOptionPane.showMessageDialog(this, new String[]{"Unable to find instruments:  ", sqle.getMessage()}, "Error!", JOptionPane.ERROR_MESSAGE);
        }
    }


    private void createUIComponents() {
        this.gatherData();


        cmbInstrument = new JComboBox(iInstruments);
        cmbNewInstrument = new JComboBox(iInstruments);
        try {
            iProjects = Project.getAllUnfinishedProjectsForInstrument(iConnPriority, iInstruments[0].getInstrumentid());
            if (iProjects.length > 0) {
                if (iProjects[0] != null) {
                    iProject = iProjects[0];
                }
            }
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(this, new String[]{"Unable to find projects for the selected instrument:  ", e.getMessage()}, "Error!", JOptionPane.ERROR_MESSAGE);
        }
        projectList = new JList(iProjects);
        projectList.setCellRenderer(new ProjectCellRenderer());

        iProjectPanel = new ProjectPanelGui(iConnPriority, 2, iProject, this, iUser, iProjects, projectList);
        projectInfoPanel = iProjectPanel.getContentPane();

    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        createUIComponents();
        jpanContent = new JPanel();
        jpanContent.setLayout(new GridBagLayout());
        GridBagConstraints gbc;
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.gridheight = 2;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        jpanContent.add(projectInfoPanel, gbc);
        projectListPanel = new JPanel();
        projectListPanel.setLayout(new GridBagLayout());
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        jpanContent.add(projectListPanel, gbc);
        projectListPanel.setBorder(BorderFactory.createTitledBorder(null, "Project list", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.ABOVE_TOP, new Font(projectListPanel.getFont().getName(), projectListPanel.getFont().getStyle(), 16)));
        final JLabel label1 = new JLabel();
        label1.setText("Select an instrument:");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(5, 5, 5, 5);
        projectListPanel.add(label1, gbc);
        final JScrollPane scrollPane1 = new JScrollPane();
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 5;
        gbc.gridwidth = 2;
        gbc.gridheight = 5;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.insets = new Insets(5, 5, 5, 5);
        projectListPanel.add(scrollPane1, gbc);
        scrollPane1.setViewportView(projectList);
        downButton = new JButton();
        downButton.setText("down");
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 8;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5);
        projectListPanel.add(downButton, gbc);
        saveChangesButton = new JButton();
        saveChangesButton.setText("Save priority changes");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 11;
        gbc.gridwidth = 3;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5);
        projectListPanel.add(saveChangesButton, gbc);
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5);
        projectListPanel.add(cmbInstrument, gbc);
        final JLabel label2 = new JLabel();
        label2.setText("Project priority list:");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 4;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(5, 5, 5, 5);
        projectListPanel.add(label2, gbc);
        upButton = new JButton();
        upButton.setText("up");
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 7;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5);
        projectListPanel.add(upButton, gbc);
        final JPanel spacer1 = new JPanel();
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 9;
        gbc.fill = GridBagConstraints.VERTICAL;
        projectListPanel.add(spacer1, gbc);
        final JPanel spacer2 = new JPanel();
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 6;
        gbc.fill = GridBagConstraints.VERTICAL;
        projectListPanel.add(spacer2, gbc);
        changeSelectedProjectToButton = new JButton();
        changeSelectedProjectToButton.setText("Change selected project to another instrument : ");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 10;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5);
        projectListPanel.add(changeSelectedProjectToButton, gbc);
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 10;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5);
        projectListPanel.add(cmbNewInstrument, gbc);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return jpanContent;
    }


    class ProjectCellRenderer extends DefaultListCellRenderer {

        /* This is the only method defined by ListCellRenderer.  We just
        * reconfigure the Jlabel each time we're called.
        */
        public Component getListCellRendererComponent(JList list,
                                                      Object value,   // value to display
                                                      int index,      // cell index
                                                      boolean iss,    // is the cell selected
                                                      boolean chf)    // the list and the cell have the focus
        {

            JLabel lLabel = null;
            Project lProject = (Project) value;
            lLabel = new JLabel(lProject.getName());
            try {
                Log lLog = Log.getNewestLogForProject(iConnPriority, lProject.getProjectid());
                if (lLog.getStatus().equalsIgnoreCase("accepted")) {
                    //do nothing
                } else {

                    if (lLog.getStatus().equalsIgnoreCase("Running")) {
                        lLabel.setOpaque(true);
                        lLabel.setBackground(Color.RED);
                    } else {
                        lLabel.setOpaque(true);
                        lLabel.setBackground(Color.GREEN);
                    }

                }


            } catch (SQLException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }


            if (iss || chf) {
                lLabel.setOpaque(true);
                lLabel.setBackground(new Color(118, 145, 239));
            }

            return lLabel;
        }
    }

}
